package repository;


import java.util.ArrayList;
import java.util.List;

import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import model.Club;
import model.Club_;

import common.BaseRepository;

/**
 * Repository class for the {@link Club} entity.
 */
public class ClubRepository extends BaseRepository<Club> {

	
	/**
	 * Find a club given its exact name or exact code
	 * @param criteria - {@link ClubSO}
	 * @return {@link List} of {@link Club}
	 */
	public List<Club> findClub(ClubSO criteria) {
		if (criteria == null) {
			return null;
		}
		CriteriaBuilder cb = getCriteriaBuilder();
		CriteriaQuery<Club> query = cb.createQuery(Club.class);
		Root<Club> root = query.from(Club.class);
		
		List<Predicate> p = getPredicates(root, criteria, cb);
		query.where(cb.or(p.toArray(new Predicate[p.size()])));
		query.select(root);
		
		return getEm().createQuery(query).getResultList();
	}
	
	/**
	 * Complete the clubs given a criteria.
	 * @param criteria - {@link ClubSO}
	 * @return a {@link List} of {@link Club}
	 */
	public List<Club> completeClub(ClubSO criteria) {
		if (criteria == null) {
			return null;
		}
		CriteriaBuilder cb = getCriteriaBuilder();
		CriteriaQuery<Club> query = cb.createQuery(Club.class);
		Root<Club> root = query.from(Club.class);
		
		List<Predicate> p = getPredicatesForAutocomplete(root, criteria, cb);
		query.where(cb.or(p.toArray(new Predicate[p.size()])));
		query.select(root);
		
		return getEm().createQuery(query).getResultList();
	}
	
	/**
	 * Get the list of predicates given the search criteria.
	 * @param root - {@link Root}
	 * @param criteria - {@link ClubSO}
	 * @param cb - {@link CriteriaBuilder}
	 * @return a {@link List} of {@link Predicate}
	 */
	private List<Predicate> getPredicates(Root<Club> root, ClubSO criteria, CriteriaBuilder cb) {
		List<Predicate> p = new ArrayList<Predicate>();
		if (criteria.getCode() != null) {
			p.add(cb.equal(root.get(Club_.code),criteria.getCode()));
		}
		if (criteria.getName() != null) {
			p.add(cb.equal(root.get(Club_.name),criteria.getName()));
		}
		return p;
	}
	
	/**
	 * Get the predicates for auto complete (add the wildcards)
	 * @param root - {@link Root}
	 * @param criteria - {@link ClubSO}
	 * @param cb - {@link CriteriaBuilder}
	 * @return a {@link List} of {@link Predicate}
	 */
	private List<Predicate> getPredicatesForAutocomplete(Root<Club> root, ClubSO criteria, CriteriaBuilder cb) {
		List<Predicate> p = new ArrayList<Predicate>();
		if (criteria.getCode() != null) {
			p.add(cb.like(cb.upper(root.get(Club_.code)),criteria.getCode()+"%"));
		}
		if (criteria.getName() != null) {
			p.add(cb.like(cb.upper(root.get(Club_.name)),criteria.getName()+"%"));
		}
		return p;
	}
	
	/**
	 * Delete the entity with the given code
	 * @param code - {@link String}
	 */
	public void delete(String code) {
		CriteriaBuilder cb = getCriteriaBuilder();
		CriteriaQuery<Club> query = cb.createQuery(Club.class);
		Root<Club> club = query.from(Club.class);
		
		query.where(cb.equal(club.get(Club_.code),code));
		query.select(club);
		Club entity;
		try {
			entity = getEm().createQuery(query).getSingleResult();
		} catch (NoResultException e) {
			entity = null;
		}
		if (entity == null) {
			return;
		}
		delete(entity);
	}
}
